package com.ng.desktop.view.receta;

import java.awt.Dimension;
import java.awt.Frame;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.util.ArrayList;
import java.util.List;

import javax.swing.BorderFactory;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;

import com.ng.desktop.model.Alimento;
import com.ng.desktop.model.Receta;
import com.ng.desktop.persistence.RecetaPersistence;
import com.ng.desktop.services.NGFactoryBean;
import com.ng.desktop.services.THListingService;
import com.ng.framework.persistence.NGListingBean;
import com.ng.framework.view.desktop.NGDualList;
import com.ng.framework.view.desktop.NGEditDialog;

public class RecetaEditDialog extends NGEditDialog<Receta, RecetaPersistence> {
	
	private static final long serialVersionUID = 62581519692799470L;

	private JTextField textFieldNombre;
	private NGDualList<NGListingBean> dualListAlimentos;
	private JTextArea textAreaDescripcion;
	private THListingService thListingService;
	
	public RecetaEditDialog(Frame owner, RecetaPersistence persistence) {
		this(owner, persistence, null);
	}

	public RecetaEditDialog(Frame owner, RecetaPersistence persistence, Receta instance) {
		super(owner, persistence, instance);
		
		this.setTitle("Gestión de Receta");
		this.setSize(new Dimension(400, 500));
	}

	@Override
	protected JPanel createDetailPanel() {
		JPanel detailPanel = new JPanel(new GridBagLayout());
		
		detailPanel.add(new JLabel("Nombre:"), new GridBagConstraints(0, 0, 1, 1, 0, 0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(0, 0, 5, 5), 0, 0));
		detailPanel.add(this.getTextFieldNombre(), new GridBagConstraints(1, 0, 1, 1, 1, 0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 5, 0), 0, 0));
		
		detailPanel.add(this.getDualListAlimentos(), new GridBagConstraints(0, 1, 2, 1, 1, 0.75, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 0, 5, 0), 0, 0));
		
		JScrollPane scrollPane = new JScrollPane(this.getTextAreaDescripcion(), JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
		scrollPane.setBorder(BorderFactory.createTitledBorder("Descripción"));
		detailPanel.add(scrollPane, new GridBagConstraints(0, 2, 2, 1, 1, 1, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0));
		
		return detailPanel;
	}
	
	private JTextField getTextFieldNombre() {
		if(textFieldNombre == null) {
			textFieldNombre = new JTextField();
		}
		return textFieldNombre;
	}
	
	private NGDualList<NGListingBean> getDualListAlimentos() {
		if(dualListAlimentos == null) {
			dualListAlimentos = new NGDualList<NGListingBean>(NGListingBean.class);
			dualListAlimentos.setLeftListElements(this.getThListingService().getList(
				THListingService.ALIMENTOS, null, null));
			
			dualListAlimentos.setBorder(BorderFactory.createTitledBorder("Alimentos"));
		}
		return dualListAlimentos;
	}
	
	private JTextArea getTextAreaDescripcion() {
		if(textAreaDescripcion == null) {
			textAreaDescripcion = new JTextArea();
			textAreaDescripcion.setLineWrap(true);
			textAreaDescripcion.setWrapStyleWord(true);
		}
		return textAreaDescripcion;
	}

	@Override
	protected void populateDetailPanel(Receta instance) {
		this.getTextFieldNombre().setText(instance.getNombre());
		this.getDualListAlimentos().setLeftListElements(this.getLeftListContent(instance.getAlimentos()));
		this.getDualListAlimentos().setRightListElements(this.getRightListContent(instance.getAlimentos()));
		this.getTextAreaDescripcion().setText(instance.getDescripcion());
	}
	
	private List<NGListingBean> getLeftListContent(List<Alimento> alimentos) {
		List<NGListingBean> all = new ArrayList<NGListingBean>(this.getThListingService().getList(
				THListingService.ALIMENTOS, null, null));
		List<NGListingBean> toRemove = new ArrayList<NGListingBean>();
		
		for(Alimento alimento : alimentos) {
			for(NGListingBean ngListingBean : all) {
				if(ngListingBean.getId().equals(alimento.getId())) {
					toRemove.add(ngListingBean);
					
					break;
				}
			}
		}
		
		all.removeAll(toRemove);
		
		return all;
	}
	
	private List<NGListingBean> getRightListContent(List<Alimento> alimentos) {
		List<NGListingBean> all = new ArrayList<NGListingBean>(this.getThListingService().getList(
				THListingService.ALIMENTOS, null, null));
		List<NGListingBean> toAdd = new ArrayList<NGListingBean>();
		
		for(Alimento alimento : alimentos) {
			for(NGListingBean ngListingBean : all) {
				if(ngListingBean.getId().equals(alimento.getId())) {
					toAdd.add(ngListingBean);
					
					break;
				}
			}			
		}
		
		return toAdd;
	}
	
	private THListingService getThListingService() {
		if(thListingService == null) {
			thListingService = (THListingService) NGFactoryBean
					.getInstance().getBean("thListingService");
		}
		return thListingService;
	}

	@Override
	protected boolean validateInput() {
		boolean valid = true;
		
		if(StringUtils.isEmpty(this.getTextFieldNombre().getText())) {
			JOptionPane.showMessageDialog(this, "El campo 'Nombre' es obligatorio.", "Error", JOptionPane.ERROR_MESSAGE);
			this.getTextFieldNombre().requestFocus();
			
			valid = false;
		} else if(CollectionUtils.isEmpty(this.getDualListAlimentos().getRightListElements())) {
			JOptionPane.showMessageDialog(this, "Debe seleccionar por lo menos un alimento de la lista.", "Error", JOptionPane.ERROR_MESSAGE);
			
			valid = false;
		} else if(StringUtils.isEmpty(this.getTextAreaDescripcion().getText())) {
			JOptionPane.showMessageDialog(this, "El campo 'Descripción' es obligatorio.", "Error", JOptionPane.ERROR_MESSAGE);
			this.getTextAreaDescripcion().requestFocus();
			
			valid = false;
		}
		
		return valid;
	}

	@Override
	protected Receta createNewInstance() {
		return new Receta();
	}

	@Override
	protected void populateInstance(Receta instance) {
		instance.setAlimentos(this.toAlimentos(this.getDualListAlimentos().getRightListElements()));
		instance.setDescripcion(this.getTextAreaDescripcion().getText());
		instance.setNombre(this.getTextFieldNombre().getText());
	}
	
	private List<Alimento> toAlimentos(List<NGListingBean> ngListingBeans) {
		List<Alimento> alimentos = new ArrayList<Alimento>();
		
		for(NGListingBean ngListingBean : ngListingBeans) {
			alimentos.add(this.getThListingService().getHydratedBean(ngListingBean, Alimento.class));
		}
		
		return alimentos;
	}

}
